package cpr.context;

import java.io.File;
import java.util.Enumeration;
import java.util.Properties;
import java.util.Set;

import cpr.ContextPropertyReader;
import cpr.IOContext;
import cpr.Printer;
import cpr.helper.ScoreHelper;
import data.Dictionary;

public class Context {
	
	public Context(Properties props) {
		printContext = new PrintContext(this);
		selectContext = new SelectContext(this);
		scoreHelper = new ScoreHelper();
		properties = props;
		reader = new ContextPropertyReader(this);
        globalRuleCache = new CacheRuleContext();
        
		updateCurrentWorksetContext("default");
		init();
	}
	public SelectContext getSelectContext() {
		return selectContext;
	}

    public CacheRuleContext getGlobalRuleCache() {
        return globalRuleCache;
    }
    
	private void closePurposeContext(IPurposeContext pc) {
		if (pc!=null) {
			pc.close();
		}
	}
	public void setCurrentSolveContext(SolveContext sctx) {
		closePurposeContext(currentSolveContext);
		this.currentSolveContext = sctx;
	}
	public SolveContext assertCurrentSolveContext() {
		if (currentSolveContext == null) {
			throw new RuntimeException("current solve context is null");
		}
		return currentSolveContext;
	}
	public SolveContext getCurrentSolveContext() {
		return currentSolveContext;
	}
	public WorksetContext getCurrentWorksetContext() {
		return currentWorksetContext;
	}
	
	public void updateCurrentWorksetContext(String wsName) {
		if ((currentWorksetContext==null)|| !currentWorksetContext.getWorksetName().equals(wsName)) {
			closePurposeContext(currentWorksetContext);
			currentWorksetContext = new WorksetContext(this,wsName);
		}
	}

    public IOContext getIOContext() {
        if (ioContext == null) {
            ioContext = new IOContext(this);
        }
        return ioContext;
    }
    public RenumberContext getRenumberContext() {
		if (renumberContext == null) {
			renumberContext = new RenumberContext(this);
		}
		return renumberContext;
	}
	public void setProperty(String key, Object value) {
		reader.setProperty(key, value);
	}
	public Object getProperty(String property) {
		return reader.getProperty(property);
	}
	public Set getPropertyKeys() {
		return reader.getPropertyKeys();
	}
	
	public void init() {
		StringBuffer sb = new StringBuffer();
        for (Enumeration iter = properties.keys(); iter.hasMoreElements();) {
            String key = (String) iter.nextElement();
            String value = properties.getProperty(key);
            Printer.print(""+key+" = "+value+"\n");
            sb.append(key+"="+value+"\n");
            reader.setProperty(key,value);
        }

	}
	
	
   public String resolveOutputFilePath() {
	   String fileNameOutput = getRawDataFilePath()+".output";
	   if (fileNameOutput == null) return null;
       try {
       	File f = new File(fileNameOutput+".txt");
       	if (f.exists()) {
       		int secondWriterSuffix = 1;
       		while (new File(fileNameOutput+secondWriterSuffix+".txt").exists()) {
       			secondWriterSuffix++;
       		}
       		fileNameOutput = fileNameOutput+secondWriterSuffix;
       	}
       	outputFilePath = fileNameOutput+".txt";
       	return outputFilePath;
       } catch (Exception ex) {
    	   throw new RuntimeException(ex);
       }
   }
   public String getOutputFilePath() {
	   if (outputFilePath==null) {
		   resolveOutputFilePath();
	   }
       return outputFilePath;
    }
   public ScoreHelper getScoreHelper() {
		return scoreHelper;
	}
	public PrintContext getPrintContext() {
		return printContext;
	}
	// normally renumbered
	public String getSubqubeDataFilename() {
		return IMAGE_QUBE_CSV;
	}

	public void setSubqubeDataFilename(String fname) {
		IMAGE_QUBE_CSV = fname;
	}

	public String getDefaultDataFolder() {
		if (DATA_FOLDER==null) {
			DATA_FOLDER = ".";
		}
		if (!DATA_FOLDER.endsWith(File.separator)) {
			DATA_FOLDER = DATA_FOLDER + File.separator;
		}
		return DATA_FOLDER;
	}
	
	public void setDefaultDataFolder(String f) {
		DATA_FOLDER = f;
	}
	public String getPureDigitalDataFilePath() {
		return getPureDigitalDataFilenameFor(getRawDataFilePath());
	}
	
	public String getDigitalDataFilePath() {
		return getDigitalDataFilenameFor(getRawDataFilePath());
	}
	
	public String getDigitalDataFilenameFor(String rawFile) {
		return rawFile+".dig";
	}
	public String getPureDigitalDataFilenameFor(String rawFile) {
		return rawFile+".puredig";
	}

	
	public String[] getStartupCommands() {
		return startupCommands;
	}
	public void setStartupCommands(String[] cmds) {
		startupCommands = cmds;
	}
    
    public int getSplitLowLimit() {
        return SPLIT_LOW_LIMIT;
    }
    public void setSplitLowLimit(int l) {
        SPLIT_LOW_LIMIT = l;
    }
    public int getSplitLimit() {
        return SPLIT_LIMIT;
    }
    public void setSplitLimit(int l) {
        SPLIT_LIMIT = l;
    }
    
    
	// NOT renumbered!
	public String getRawDataFilename() {
		return HL_CSV_FILE_RAW;
	}
	
	public String getDictDataFilePath() {
		return getRawDataFilePath()+".dict";
	}
	public String getRawDataFilePath() {
		return getDefaultDataFolder()+HL_CSV_FILE_RAW;
	}

	
	
	public Dictionary getDictionary() {
		if (dictionary==null) {
			dictionary = new Dictionary();
			dictionary.setPath(getDictDataFilePath());
		}
		return dictionary;
	}
	public void resetDictionary() {
		dictionary = null;
	}
	
	public void setRawDataFilename(String fname) {
		HL_CSV_FILE_RAW = fname;
	}

	
	public void changeFilepath() {
		String newOutputFile = resolveOutputFilePath();
		//Printer.close();
		Printer.setSecordWriter(newOutputFile);
	}
	
	public boolean isVerbose() {
		return VERBOSE;
	}
	public void setVerbose(boolean v) {
		VERBOSE = v;
	}

	public boolean isDigital() {
		return DIGITAL;
	}
	public void setDigital(boolean d) {
		DIGITAL = d;
	}
	public int getRulesToLoad() {
		return RULES_TO_LOAD;
	}

	public void setRulesToLoad(int i) {
		RULES_TO_LOAD = i;
	}

	public int getMasterRule() {
		return IMAGE_RULE;
	}

	public void setMasterRule(int r) {
		IMAGE_RULE = r;
	}

	public int getRootScore() {
		return IMAGE_SCORE;
	}

	public void setRootScore(int sc) {
		IMAGE_SCORE = sc;
	}

	public int getBufferSize() {
		return BUFFER_SIZE;
	}

	public void setBufferSize(int b) {
		BUFFER_SIZE = b;
	}
	
//	public void setINITIAL_NUMBER_OF_RULES_IN_SOLUTION(int i) {
//		INITIAL_NUMBER_OF_RULES_IN_SOLUTION = i;
//	}
//	public int getINITIAL_NUMBER_OF_RULES_IN_SOLUTION() {
//		return INITIAL_NUMBER_OF_RULES_IN_SOLUTION;
//	}
	private ContextPropertyReader reader;
    private CacheRuleContext globalRuleCache;
	private Properties properties = null;
	
	private int BUFFER_SIZE;

	private int IMAGE_RULE;

	private int IMAGE_SCORE;

	private int RULES_TO_LOAD;

	private String HL_CSV_FILE_RAW;
	
	private String DATA_FOLDER;
	
	private Dictionary dictionary;
    
    private int SPLIT_LIMIT, SPLIT_LOW_LIMIT;
    
    private String[] startupCommands;

	private String IMAGE_QUBE_CSV;
	private int INITIAL_NUMBER_OF_RULES_IN_SOLUTION = 0;
	
	private String HL_CSV_FILE;

	private RenumberContext renumberContext;
	private WorksetContext currentWorksetContext;
	private SolveContext currentSolveContext;
//	private SolveContext solveContext;
	private PrintContext printContext;
	private String outputFilePath = null;
	private SelectContext selectContext;
	private ScoreHelper scoreHelper;
    private IOContext ioContext;
	
	private boolean VERBOSE = false;
	
	private boolean DIGITAL = true;


}
